package com.wyvoid.forum.interceptor;

import com.wyvoid.forum.annotations.Secure;
import com.wyvoid.forum.annotations.LoginUser;
import com.wyvoid.forum.annotations.LoginAdmin;
import com.wyvoid.forum.web.MyActionBeanContext;
import com.wyvoid.forum.exception.user.UserNotLoginException;
import com.wyvoid.forum.exception.user.AuthorizationException;
import com.wyvoid.forum.exception.admin.AdminException;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.controller.ExecutionContext;
import net.sourceforge.stripes.controller.Interceptor;
import net.sourceforge.stripes.controller.Intercepts;
import net.sourceforge.stripes.controller.LifecycleStage;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * User: cjp
 * Date: 2007-6-27
 * Time: 20:22:02
 */

@Intercepts(LifecycleStage.HandlerResolution)
public class SecurityInterceptor implements Interceptor {
    public Resolution intercept(ExecutionContext ctx) throws Exception {
        Resolution resolution = ctx.proceed();

        MyActionBeanContext context = ((MyActionBeanContext) ctx.getActionBeanContext());
        //得到当前正在执行的action的方法
        Method handlerMethod = ctx.getHandler();

         //如果当前方法要求用户登录,并且用户没有登录,重定向到登录页面
        LoginUser loginUser = getAnnotation(handlerMethod, LoginUser.class);
        if (loginUser != null && !context.isUserLoggedIn()) {
            throw new UserNotLoginException();
        }

        //如果当前方法要求管理员身份登录,并且没有登录,重定向到登录页面
        LoginAdmin loginAdmin = getAnnotation(handlerMethod, LoginAdmin.class);
        if(loginAdmin!=null&&!context.isAdminLoggerIn()){
            throw new AdminException();
        }

        Secure secure = getAnnotation(handlerMethod, Secure.class);

//        context.autoLogin();

        if (secure == null) {
            return resolution;
        }

        String authorityStr = secure.authority();
        if (!context.canAccess(authorityStr)) {
            throw new AuthorizationException();
        } else {
            return resolution;
        }
    }

    public <T extends Annotation> T getAnnotation(Method method, Class<T> clazz) {
        Annotation annotation = method.getAnnotation(clazz);
        if (annotation == null) {
            Class beanClass = method.getDeclaringClass();
            annotation = beanClass.getAnnotation(clazz);
            if (annotation == null) {
                Class parent = beanClass.getSuperclass();
                if (ActionBean.class.isAssignableFrom(parent))
                    annotation = parent.getAnnotation(clazz);
            }
        }
        return (T) annotation;
    }

}
